//哈希表,Native化作为内置对象
var Hash = new Native({

 //族名,类名,用于$type方法的精准类型判断
 name: 'Hash',

 initialize: function(object){

  //对于哈希表的实例,复制副本以解除两者的引用/链接关系
  if ($type(object) == 'hash') ōbject = $unlink(object.getClean());

  //再复制到当前实例
  for (var key in object) this[key] = object[key];
  return this;
 }

});

//对哈希表的扩展的实现
Hash.implement({

 //哈希表长度(键值数统计,不包括值型为函数的)
 getLength: function(){
  var length = 0;
  for (var key in this){
   //hasOwnProperty判断是否具有指定名称的属性,注意是属性,不包括方法
   if (this.hasOwnProperty(key)) length++;
  }
  return length;
 },

 //迭代,同时是只遍历属性,这个也很符合实际使用的情况
 forEach: function(fn, bind){
  for (var key in this){
   if (this.hasOwnProperty(key)) fn.call(bind, this[key], key, this);
  }
 },
 
 //复制一个副本,不知道为什么用这个不容易理解的名字
 getClean: function(){
  var clean = {};
  for (var key in this){
   if (this.hasOwnProperty(key)) clean[key] = this[key];
  }
  return clean;
 }

});

//将each作为forEach的别名
Hash.alias('forEach', 'each');

//转为哈希表的快捷方式
function $H(object){
 return new Hash(object);
};

//额外的扩展
Hash.implement({

 //hasOwnProperty的快捷方式
 has: Object.prototype.hasOwnProperty,

 //根据值找对应的键
 keyOf: function(value){
  for (var key in this){
   if (this.hasOwnProperty(key) && this[key] === value) return key;
  }
  return null;
 },

 //查找是否存在指定值
 hasValue: function(value){
  return (Hash.keyOf(this, value) !== null);
 },

 //数据扩展，会覆盖原数据
 extend: function(properties){
  Hash.each(properties, function(value, key){
   Hash.set(this, key, value);
  }, this);
  return this;
 },

 //合并，不包括重复项
 combine: function(properties){
  Hash.each(properties, function(value, key){
   Hash.include(this, key, value);
  }, this);
  return this;
 },

 //探险指定键值
 erase: function(key){
  if (this.hasOwnProperty(key)) delete this[key];
  return this;
 },

 //根据键名读取值
 get: function(key){
  return (this.hasOwnProperty(key)) ? this[key] : null;
 },

 //设置键-值
 set: function(key, value){
  if (!this[key] || this.hasOwnProperty(key)) this[key] = value;
  return this;
 },

 //清空哈希表
 empty: function(){
  Hash.each(this, function(value, key){
   delete this[key];
  }, this);
  return this;
 },

 //包含新键-值，如果旧数据中不存在该键名
 include: function(key, value){
  var k = this[key];
  if (!$defined(k)) this[key] = value;
  return this;
 },

 //类似Array对象的map方法，区别在于传给fn方法的参数
 map: function(fn, bind){
  var results = new Hash;
  Hash.each(this, function(value, key){
   results.set(key, fn.call(bind, value, key, this));
  }, this);
  return results;
 },

 //类似Array对象的filter方法，区别在于传给fn方法的参数
 filter: function(fn, bind){
  var results = new Hash;
  Hash.each(this, function(value, key){
   if (fn.call(bind, value, key, this)) results.set(key, value);
  }, this);
  return results;
 },

 //类似Array对象的every方法，区别在于传给fn方法的参数
 every: function(fn, bind){
  for (var key in this){
   if (this.hasOwnProperty(key) && !fn.call(bind, this[key], key)) return false;
  }
  return true;
 },

 //类似Array对象的some方法，区别在于传给fn方法的参数
 some: function(fn, bind){
  for (var key in this){
   if (this.hasOwnProperty(key) && fn.call(bind, this[key], key)) return true;
  }
  return false;
 },

 //获取哈希表中的所有键，以数组返回
 getKeys: function(){
  var keys = [];
  Hash.each(this, function(value, key){
   keys.push(key);
  });
  return keys;
 },

 //获取哈希表中的所有值，以数组返回
 getValues: function(){
  var values = [];
  Hash.each(this, function(value){
   values.push(value);
  });
  return values;
 },
 
 //将哈希表数据转为表单提交形式的查询串
 toQueryString: function(base){
  var queryString = [];
  Hash.each(this, function(value, key){
   if (base) key = base + '[' + key + ']';
   var result;
   switch ($type(value)){
    case 'object': result = Hash.toQueryString(value, key); break;
    case 'array':
     var qs = {};
     value.each(function(val, i){
      qs[i] = val;
     });
     result = Hash.toQueryString(qs, key);
    break;
    default: result = key + '=' + encodeURIComponent(value);
   }
   if (value != undefined) queryString.push(result);
  });
  
  return queryString.join('&');
 }

});

//分别为keyOf和hasValue建立indexOf和contains的别名方法
Hash.alias({keyOf: 'indexOf', hasValue: 'contains'});